/*
* api请求文件，统一处理http结果
* timeout时间为15s
* 不符合此文件封装配置的，例如果上传文件，超过15s，建议使用全局的对象axios处理请求，例如在vue单文件中，可直接使用this.$axios
*/
import Vue from 'vue';
import axios from 'axios';
import qs from 'qs';
import { handleRsp } from './handler';
import apiMap from './apiMap';

// 将axios对象挂载到vue全局实例中, 不符合实例配置的请求，可以直接使用axios对象直接请求
Vue.prototype.$axios = axios;

const API = {};

// 内存缓存
let storage = {};

// 创建一个axios实例
const instance = axios.create();
// 实例的超时时间，只在当前实例生效
instance.defaults.timeout = 15 * 1000;

['get', 'post'].forEach((method) => {
  API[method] = (url, data, headers = {}) => new Promise((resolve, reject) => {
    if (headers === 'json') {
      headers = {};
      headers['Content-Type'] = 'application/json';
    }
    let opt;
    if (method === 'get') {
      opt = { params: data };
    } else if (headers['Content-Type'] === 'application/json') { // 当post请求是json格式时
      opt = data;
    } else {
      opt = qs.stringify(data, { allowDots: true }); // formdata格式
    }
    if (!apiMap[url]) {
      throw new Error('url 未定义在apiMap中');
    }
    instance[method](apiMap[url], opt, headers).then((response) => {
      handleRsp(response, resolve, reject);
    }, (err) => {
      if (err.response) {
        handleRsp(err.response, resolve, reject);
      } else {
        handleRsp(err, resolve, reject);
      }
    }).catch((err) => {
      handleRsp(err, resolve, reject);
    });
  });
});

// 缓存get请求
API.cache = (url, data, headers = {}) => new Promise((resolve, reject) => {
  let key = Object.assign({}, data);
  key.url = url;
  // 将所有url参数，作为字符串当作key值
  key = JSON.stringify(key);
  if (storage[key]) {
    setTimeout(() => {
      if (typeof storage[key] === 'object') {
        resolve(JSON.parse(JSON.stringify(storage[key])));
      } else {
        resolve(storage[key]);
      }
    }, 100);
  } else {
    API.get(apiMap[url], data, headers).then((result) => {
      storage[key] = result;
      resolve(result);
    }).catch((err) => {
      reject(err);
    });
  }
});

// 清理缓存
API.clearCache = () => {
  storage = {};
};

export default API;
